package com.ygqh.baby.service.impl;

import com.ygqh.baby.ao.*;
import com.ygqh.baby.mapper.YgProductSecondMapper;
import com.ygqh.baby.model.YgProduct4ListModel;
import com.ygqh.baby.po.YgProductSecond;
import com.ygqh.baby.po.YgProductSecondDetail;
import com.ygqh.baby.po.YgProductSecondExample;
import com.ygqh.baby.service.YgProductSecondDetailService;
import com.ygqh.baby.service.YgProductSecondService;
import com.ygqh.baby.service.task.YgProductSecondTaskService;
import com.ygqh.baby.utils.DateConvertUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@Service
public class YgProductSecondServiceImpl implements YgProductSecondService {

    @Autowired
    private YgProductSecondMapper ygProductSecondMapper;
    @Autowired
    private YgProductSecondDetailService ygProductSecondDetailService;
    @Autowired
    private YgProductSecondTaskService ygProductSecondTaskService;

    @Override
    public List<YgProductSecond> find() {
        YgProductSecondExample example = new YgProductSecondExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygProductSecondMapper.selectByExample(example);
    }

    @Override
    public int findCount() {
        YgProductSecondExample example = new YgProductSecondExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygProductSecondMapper.countByExample(example);
    }

    @Override
    public YgProductSecond findById(Long id) {
        return ygProductSecondMapper.selectByPrimaryKey(id);
    }

    @Override
    public ResultSet<YgProductSecond> search(QueryInfo queryInfo, Long supplierId, PromotionStatus pStatus,
                                             Date startTime, Date endTime, String q) {
        int count = ygProductSecondMapper.countSuper(supplierId, pStatus == null ? null : pStatus.name(),
                startTime, endTime, q);
        if (count == 0) {
            return new ResultSet<>();
        }
        List<YgProductSecond> list = ygProductSecondMapper.selectSuper(queryInfo, supplierId,
                pStatus == null ? null : pStatus.name(), startTime, endTime, q);
        list.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
        return new ResultSet<>(count, list);
    }

    @Override
    public int deleteSoft(Long[] ids) {
        Assert.notEmpty(ids);
        YgProductSecondExample example = new YgProductSecondExample();
        example.createCriteria().andIdIn(Arrays.asList(ids));
        YgProductSecond record = new YgProductSecond();
        record.setStatus(DataStatus.Delete);
        return ygProductSecondMapper.updateByExampleSelective(record, example);
    }

    @Override
    public int deleteSoft(Long id) {
        return this.deleteSoft(new Long[]{id});
    }

    @Override
    public int saveOrUpdate(YgProductSecond ygProductSecond) {
        int r = 0;
        if (ygProductSecond.getId() != null) {
            this.update(ygProductSecond);
        } else {
            this.save(ygProductSecond);
        }
        return r;
    }

    @Override
    public List<YgProduct4ListModel> findProductBySecondId(QueryInfo queryInfo, Long secondId, String productName,
                                                           Long groupId) {
        return ygProductSecondMapper.selectProductBySecondId(queryInfo, secondId, productName, groupId);
    }

    @Override
    public YgProductSecond findActive() {
        return findActive(SalesPlatform.Yiigoo);
    }

    @Override
    public YgProductSecond findActive(SalesPlatform salesPlatform) {
        return ygProductSecondMapper.selectActive(salesPlatform);
    }

    @Override
    public Boolean selectSecondByTime(Date startTime, Date endTime, Long secondId) {
        List<YgProductSecond> secondList = ygProductSecondMapper.selectSecondByTime(startTime, endTime, secondId);
        return secondList != null && secondList.size() > 0;
    }

    @Override
    public List<YgProduct4ListModel> findBySpecifyDate(Date specifyDate) {
        return findBySpecifyDate(specifyDate, SalesPlatform.Yiigoo);
    }

    @Override
    public List<YgProduct4ListModel> findBySpecifyDate(Date specifyDate, SalesPlatform salesPlatform) {
        if (specifyDate == null) {
            specifyDate = new Date();
        }
        Date startTime = DateConvertUtils.parse(DateConvertUtils.format(specifyDate), "yyyy-MM-dd");
        Date endTime = DateConvertUtils.addDay(startTime, 1);
        return ygProductSecondMapper.selectProductBySpecifyDate(startTime, endTime, salesPlatform);
    }

    @Override
    public Message findSecondDateByProductId(Long productId) {
        if (productId == null) {
            return Message.error("未指定商品", null);
        }
        Date startTime = DateConvertUtils.getDateStart(new Date());
        YgProductSecond second = ygProductSecondMapper.selectByProductIdAndStartTime(productId, startTime);
        if (second == null) {
            return Message.success(null);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("currentTime", new Date());
        data.put("startTime", second.getStartTime());
        data.put("endTime", second.getEndTime());
        return Message.success(data);
    }

    @Override
    public Message findUnEndByPid(Long productId) {
        if (productId == null) {
            return Message.error("未指定商品", null);
        }
        YgProductSecond second = ygProductSecondMapper.selectUnEndByPid(productId, new Date());
        if (second == null) {
            return Message.success(null);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("currentTime", new Date());
        data.put("startTime", second.getStartTime());
        data.put("endTime", second.getEndTime());
        return Message.success(data);
    }

    @Override
    public Map<String, Object> findActiveSecondInfo(SalesPlatform salesPlatform) {
        Map<String, Object> data = new HashMap<>();
        YgProductSecond productSecond = ygProductSecondMapper.selectActiveWithProductInfo(salesPlatform);
        if (productSecond != null) {
            data.put("secondId", productSecond.getId());
            data.put("endTime", productSecond.getEndTime());
            data.put("currentTime", new Date());
            data.put("productList", productSecond.getProductList());
        }
        return data;
    }

    @Override
    public YgProductSecond findWithProductInfoById(Long id) {
        Assert.notNull(id, "param id can not be null");
        return ygProductSecondMapper.selectWithProductInfoById(id);
    }

    @Override
    public Message delProductSecond(Long id) {
        YgProductSecond second = this.findById(id);
        if (second == null) {
            return Message.error("活动不存在", null);
        }
        Date now = new Date();
        if (now.compareTo(second.getEndTime()) >= 0) {
            return Message.error("活动已结束", null);
        }
        if (now.compareTo(second.getStartTime()) >= 0) {
            return Message.error("活动已开始", null);
        }
        this.deleteSoft(id);
        ygProductSecondTaskService.deleteProductSecondJob(id, "Start", "delProductSecond");
        return Message.success(null);
    }

    @Override
    public Message save(YgProductSecond ygProductSecond) {
        try {
            validateParamForEdit(ygProductSecond);
        } catch (Exception e) {
            return Message.error(e.getMessage(), null);
        }
        int row = ygProductSecondMapper.insertSelective(ygProductSecond);
        if (row > 0) {
            saveProductSecondDetail(ygProductSecond);
            ygProductSecondTaskService.processSecondAfterSave(ygProductSecond.getId());
        }
        return Message.success(0);
    }

    @Override
    public Message update(YgProductSecond ygProductSecond) {
        try {
            validateParamForEdit(ygProductSecond);
        } catch (Exception e) {
            return Message.error(e.getMessage(), null);
        }
        int row = ygProductSecondMapper.updateByPrimaryKeySelective(ygProductSecond);
        if (row > 0) {
            ygProductSecondTaskService.processSecondBeforeUpdate(ygProductSecond.getId());
            updateProductSecondDetail(ygProductSecond);
            ygProductSecondTaskService.processSecondAfterSave(ygProductSecond.getId());
        }
        return Message.success(0);
    }

    /**
     * 校验待保存的数据参数
     *
     * @param ygProductSecond
     */
    private void validateParamForEdit(YgProductSecond ygProductSecond) {
        Assert.isTrue(StringUtils.isNotBlank(ygProductSecond.getSecondName()), "活动名称不能为空");
        Assert.notNull(ygProductSecond.getStartTime(), "活动开始时间不能为空");
        Assert.notNull(ygProductSecond.getEndTime(), "活动结束时间不能为空");
        Assert.isTrue(ygProductSecond.getStartTime().before(ygProductSecond.getEndTime()),
                "活动结束时间应大于活动开始时间");
        if (ygProductSecond.getId() == null) {
            Assert.isTrue(new Date().before(ygProductSecond.getEndTime()), "活动结束时间应大于当前时间");
        }
        Assert.notEmpty(ygProductSecond.getProductList(), "参与活动的商品集不能为空");
        Assert.isTrue(!selectSecondByTime(ygProductSecond.getStartTime(), ygProductSecond.getEndTime(), ygProductSecond.getId()),
                "存在交叉时间的活动,请修改活动的限制时间");
    }

    private void saveProductSecondDetail(YgProductSecond ygProductSecond) {
        List<YgProductSecondDetail> detailList = new ArrayList<>();
        ygProductSecond.getProductList().forEach(o ->
                detailList.add(new YgProductSecondDetail(ygProductSecond.getId(), o.getId(), o.getProductSecondPrice(),
                        o.getProductSalePrice(), o.getVipPrice())));
        ygProductSecondDetailService.addBatch(detailList);
    }

    private void updateProductSecondDetail(YgProductSecond ygProductSecond) {
        List<YgProductSecondDetail> dbDetailList =
                ygProductSecondDetailService.findByProductSecondId(ygProductSecond.getId());
        if (CollectionUtils.isEmpty(dbDetailList)) {
            dbDetailList = new ArrayList<>();
        }
        Map<Long, List<YgProductSecondDetail>> map = dbDetailList.stream()
                .collect(Collectors.groupingBy(YgProductSecondDetail::getProductId));
        List<YgProductSecondDetail> insertList = new ArrayList<>();
        List<YgProductSecondDetail> updateList = new ArrayList<>();
        List<Long> currentProductIdList = new ArrayList<>();
        ygProductSecond.getProductList().forEach(o -> {
            if (MapUtils.isNotEmpty(map) && CollectionUtils.isNotEmpty(map.get(o.getId()))) {
                YgProductSecondDetail detail = map.get(o.getId()).get(0);
                detail.setOriginalSalePrice(o.getProductSalePrice());
                detail.setSecondPrice(
                        o.getProductSecondPrice() == null ? o.getProductSalePrice() : o.getProductSecondPrice());
                updateList.add(detail);
            } else {
                insertList.add(new YgProductSecondDetail(ygProductSecond.getId(), o.getId(), o.getProductSecondPrice(),
                        o.getProductSalePrice(), o.getVipPrice()));
            }
            currentProductIdList.add(o.getId());
        });
        List<Long> deleteIdList = dbDetailList.stream()
                .filter(o -> currentProductIdList.indexOf(o.getProductId()) == -1)
                .map(YgProductSecondDetail::getId)
                .collect(Collectors.toList());
        ygProductSecondDetailService.addBatch(insertList);
        ygProductSecondDetailService.updateBatch(updateList);
        if (CollectionUtils.isNotEmpty(deleteIdList)) {
            ygProductSecondDetailService.deleteSoft(deleteIdList.toArray(new Long[0]));
        }
    }
}
